<template>
  <div class="search-header">
    <div class="my-note">
      <div>
        {{ selectedFolder?.label || selectedTag?.label || '' }}
        <span style="font-size: 12px; color: #999999"
          >{{ noteListTotal }}篇</span
        >
      </div>
      <span>笔记</span>
    </div>
    <div class="search">
      <el-input
        style="width: 200px"
        v-model="queryNote.keyword"
        placeholder="搜索..."
        @input="handleSearch"
      />
      <div class="sort-icons">
        <el-popover
          ref="popover"
          placement="left"
          :width="80"
          trigger="click"
          class="custom-popover"
        >
          <div
            class="btns"
            style="
              display: flex;
              flex-direction: column;
              align-items: center;
              justify-content: center;
              gap: 4px;
            "
          >
            <el-button
              style="margin: 0 !important; border: none !important; width: 100%"
              class="sort-item"
              v-for="(item, index) in sortList"
              :key="index"
              :class="{
                active: currentId === item.id,
              }"
              :type="currentId === item.id ? 'primary' : 'default'"
              @click="toggleSort(item)"
            >
              {{ item.label }}
            </el-button>
          </div>
          <template #reference>
            <el-icon v-if="down" style="cursor: pointer; font-size: 24px">
              <Desc />
            </el-icon>
            <el-icon v-else style="cursor: pointer; font-size: 24px">
              <Asc />
            </el-icon>
          </template>
        </el-popover>
        <el-icon
          v-if="isCard"
          @click="isCard = !isCard"
          style="cursor: pointer; font-size: 24px"
        >
          <Menu />
        </el-icon>
        <el-icon
          v-else
          @click="isCard = !isCard"
          style="cursor: pointer; font-size: 24px"
        >
          <Toggle />
        </el-icon>
      </div>
    </div>
  </div>
  <div class="padding-10 note-box" ref="noteBoxRef" v-loading="loading">
    <el-row :gutter="20" v-if="noteList.length && isCard" class="item-box">
      <el-popover
        v-for="(item, index) in noteList"
        :key="index"
        placement="right"
        :visible="contextmenuId === item.id"
      >
        <div class="btns-wrapper" style="display: flex; flex-direction: column">
          <el-button
            v-for="(button, n) in handleReturnOperation(item)"
            :key="n"
            style="
              margin: 0 !important;
              border: none !important;
              justify-content: flex-start;
            "
            @click="handleOpenNote(button, item)"
          >
            {{ button.label }}
          </el-button>
        </div>
        <template #reference>
          <el-card
            style="
              width: 180px;
              height: 248px;
              border: none !important;
              cursor: pointer;
            "
            shadow="hover"
            @click="handleJumpEditNote(item)"
            @contextmenu="handleMenu(item.id, $event)"
            v-click-outside="onClickOutside"
          >
            <template #header>
              <div
                class="header-btn"
                style="display: flex; flex-direction: column"
              >
                <div style="text-align: end">
                  <el-popover
                    placement="bottom"
                    :width="100"
                    trigger="hover"
                    class="custom-popover"
                  >
                    <template #reference>
                      <el-icon @click.stop="() => {}" style="cursor: pointer"
                        ><MoreFilled
                      /></el-icon>
                    </template>
                    <div
                      class="btns-wrapper"
                      style="display: flex; flex-direction: column"
                    >
                      <el-button
                        v-for="(button, n) in handleReturnOperation(item)"
                        :key="n"
                        style="
                          margin: 0 !important;
                          border: none !important;
                          justify-content: flex-start;
                        "
                        @click="handleOpenNote(button, item)"
                      >
                        {{ button.label }}
                      </el-button>
                    </div>
                  </el-popover>
                </div>
                <el-text
                  line-clamp="1"
                  style="
                    text-align: start;
                    align-self: flex-start;
                    font-weight: 600;
                  "
                >
                  {{ item.title }}
                </el-text>
              </div>
            </template>
            <el-text
              v-if="item.content && item.icon == 'Document'"
              :innerHTML="replaceImg(item.content, '160', '120')"
              line-clamp="5"
              style="width: 160px; height: 110px"
            >
            </el-text>
            <div
              style="
                width: 160px;
                height: 110px;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
              "
              v-else-if="item.icon == 'FlowChart'"
            >
              <el-icon style="font-size: 84px" class="flow-chart-color">
                <FlowChart />
              </el-icon>
              <span style="color: #aaa; font-size: 14px">流程图</span>
            </div>
            <div
              style="
                width: 160px;
                height: 110px;
                display: flex;
                align-items: center;
                flex-direction: column;
                justify-content: center;
              "
              v-else-if="item.icon == 'Xmind'"
            >
              <el-icon style="font-size: 84px" class="xmind-theme-color">
                <Xmind />
              </el-icon>
              <span style="color: #aaa; font-size: 14px">思维导图</span>
            </div>
            <div
              v-else
              style="
                display: flex;
                align-items: center;
                justify-content: center;
                height: 110px;
                cursor: pointer;
              "
            >
              <el-icon :size="56" color="#409efe"><Document /></el-icon>
            </div>
            <div class="tags" style="height: 60px">
              <el-space wrap class="tag-wrapper">
                <el-text type="primary" line-clamp="2">
                  <el-tag
                    v-for="(tag, i) in item.label"
                    :key="i"
                    type="primary"
                    size="small"
                    effect="dark"
                    style="margin: 0 2px 0 0; padding: 2px 6px"
                  >
                    <el-text style="max-width: 80px; color: #fff" truncated>
                      {{ tag.label_name }}
                    </el-text>
                  </el-tag>
                </el-text>
              </el-space>
            </div>
            <template #footer>
              {{
                item.updated_at &&
                new Date(item.updated_at).toLocaleDateString()
              }}
            </template>
          </el-card>
        </template>
      </el-popover>
    </el-row>
    <!-- <List :list="noteList" v-if="!isCard" :disabled="false"></List> -->
    <div class="list" v-if="!isCard">
      <div
        style="width: 100%; height: 100px; position: relative"
        shadow="hover"
        v-for="(item, index) in noteList"
        :key="index"
        class="card-item"
        @click="handleJumpEditNote(item)"
        @contextmenu="handleClickListItem($event, item)"
      >
        <div
          style="
            width: 40px;
            height: 100%;
            flex-shrink: 0;
            display: flex;
            justify-content: center;
            align-items: center;
          "
        >
          <el-icon
            :class="[
              item.icon === 'Document' && 'doc-theme-color',
              item.icon === 'Xmind' && 'xmind-theme-color',
              item.icon === 'FlowChart' && 'flow-chart-color',
            ]"
            :size="24"
            v-if="item.icon"
          >
            <Component :is="MapComponent[item.icon]" />
          </el-icon>
          <el-icon v-else :size="24" color="#409efe"><Document /></el-icon>
        </div>
        <div
          style="
            width: calc(100% - 40px - 180px);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            height: 100%;
          "
        >
          <el-text truncated style="width: 100%; height: 20px">
            {{ item.title }}
          </el-text>
          <el-text
            v-if="item.content && item.icon == 'Document'"
            line-clamp="2"
            style="width: 100%; height: calc(100% - 30px)"
            :innerHTML="item.content.replace(/<img\b[^>]*>/gi, '')"
          >
          </el-text>
        </div>
        <div
          style="
            width: 180px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-shrink: 0;
            height: 100%;
            padding: 0 10px;
          "
        >
          {{ new Date(item.updated_at).toLocaleDateString() }}
          <div>
            <el-popover
              placement="bottom"
              :width="100"
              trigger="hover"
              class="custom-popover"
            >
              <template #reference>
                <el-icon @click.stop="() => {}" style="cursor: pointer"
                  ><MoreFilled
                /></el-icon>
              </template>
              <div
                class="btns-wrapper"
                style="display: flex; flex-direction: column"
              >
                <el-button
                  v-for="(button, n) in handleReturnOperation(item)"
                  :key="n"
                  style="
                    margin: 0 !important;
                    border: none !important;
                    justify-content: flex-start;
                  "
                  @click="handleOpenNote(button, item)"
                >
                  {{ button.label }}
                </el-button>
              </div>
            </el-popover>
          </div>
        </div>
        <div
          v-if="itemId === item.id"
          class="operationMenu"
          style="display: flex; flex-direction: column"
          v-click-outside="handleClickOutside"
        >
          <el-button
            v-for="(button, n) in handleReturnOperation(item)"
            :key="n"
            style="
              margin: 0 !important;
              border: none !important;
              justify-content: flex-start;
            "
            @click.stop="handleOpenNote(button, item)"
          >
            {{ button.label }}
          </el-button>
        </div>
      </div>
    </div>

    <el-empty description="暂无笔记" v-if="!loading && !noteList.length" />
    <pagination
      v-if="noteList.length"
      :total="noteListTotal"
      v-model:page="queryNote.page"
      v-model:limit="queryNote.limit"
      @pagination="noteState.getList"
    />

    <el-dialog
      v-model="editTitleVisible"
      draggable
      overflow
      title="修改标题"
      width="500"
      destroy-on-close
      @close="resetForm(ruleFormRef)"
    >
      <el-form
        ref="ruleFormRef"
        style="max-width: 600px"
        :model="fileForm"
        label-width="auto"
        size="default"
        :rules="rules"
      >
        <el-form-item label="文件夹名称" prop="name">
          <el-input v-model="fileForm.name" placeholder="请输入标题" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="resetForm(ruleFormRef)">取消</el-button>
          <el-button
            type="primary"
            :loading="modifyFileLoading"
            @click="submitForm(ruleFormRef)"
          >
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>

  <Modal v-model="deleteFile" @confirm="deleteNoteConfirm"></Modal>

  <LabelModal
    v-model:visible="labelVisible"
    :rowData="appendParentData"
  ></LabelModal>

  <MoveNoteModal
    v-model="moveVisible"
    :appendParentData="appendParentData"
  ></MoveNoteModal>
</template>
<script setup>
import { ref, reactive, watch, nextTick, onMounted, onUnmounted } from 'vue'
import Modal from './components/deleteNoteModal.vue'
import LabelModal from './components/labelModal.vue'
import MoveNoteModal from './components/moveNoteModal.vue'
import {
  // httpNoteList,
  // httpNoteListWithLabel,
  httpUpdatefolder,
  httpMovefolder,
  httpDeleteNoteBook,
  httpCreateNote,
  httpPubblishNoteToNoteSpace,
  httpUnpublishFromNoteSpace,
} from '@/api/note.js'
import {
  flatTree,
  addLabel,
  downloadFile,
  debounce,
  replaceImg,
} from '@/utils/tools.ts'
import Pagination from '@/components/pagination/index.vue'
import Desc from '@/icons/Desc.vue'
import Asc from '@/icons/Asc.vue'
import Menu from '@/icons/Menu.vue'
import Toggle from '@/icons/Toggle.vue'
import List from './components/List.vue'
import { MoreFilled } from '@element-plus/icons-vue'
import useNoteStore from '@/stores/note'
import { storeToRefs } from 'pinia'
import { useRouter, useRoute } from 'vue-router'
import useNote from '@/hooks/useNote'
import { ElMessage, ElMessageBox } from 'element-plus'
import { asBlob } from 'html-docx-js-typescript'
import { enumNoteSpace } from '@/enum/note'
import { ClickOutside as vClickOutside } from 'element-plus'
import { useViewPort } from '@/hooks/useView.js'
const router = useRouter()
const route = useRoute()
const noteState = useNoteStore()

const {
  selectedFolder,
  selectedTag,
  noteData,
  noteList,
  noteListTotal,
  loading,
  queryNote,
} = storeToRefs(noteState)
const { MapJump, FlowChart, Xmind, MapComponent } = useNote()
const ruleFormRef = ref()
const modifyFileLoading = ref(false)
const fileForm = reactive({
  name: '',
}) // 重命名
const rules = reactive({
  name: [
    {
      required: true,
      message: '请输入标题名称',
      trigger: ['blur', 'change'],
    },
  ],
})
const down = ref(true)
const isCard = ref(true)
const currentId = ref(2)
const contextmenuId = ref('')
const onClickOutside = () => {
  contextmenuId.value = undefined
}
const handleMenu = (item, e) => {
  e.preventDefault()
  contextmenuId.value = item
}
const moreFilledbuttons = [
  {
    id: '1',
    label: '重命名',
  },
  {
    id: '2',
    label: '移动到',
  },
  {
    id: '3',
    label: '复制',
  },
  {
    id: '4',
    label: '粘贴',
  },
  {
    id: '5',
    label: '删除',
  },
  {
    id: '6',
    label: '导出word',
  },
  {
    id: '7',
    label: '新窗口打开',
  },
  {
    id: '8',
    label: '关联标签',
  },
  {
    id: '9',
    label: '发布到笔记空间',
  },
]
const itemId = ref('')
const { vw, vh } = useViewPort()
const handleClickOutside = (item) => {
  itemId.value = undefined
  noteBoxRef.value.style.overflow = 'auto'
}
const noteBoxRef = ref(null)
const handleClickListItem = (e, item) => {
  e.preventDefault()
  e.stopPropagation()
  itemId.value = item.id
  nextTick(() => {
    noteBoxRef.value.style.overflow = 'hidden'
  })
  let posY = e.clientY // 获取鼠标右击事件的垂直坐标
  let posX = e.clientX

  nextTick(() => {
    if (
      posX >
      vw.value - document.querySelector('.operationMenu').offsetWidth
    ) {
      posX -= document.querySelector('.operationMenu').offsetWidth // 鼠标的位置减去 元素的宽度
    }
    if (
      posY >
      vh.value - document.querySelector('.operationMenu').offsetHeight
    ) {
      posY = vh.value - document.querySelector('.operationMenu').offsetHeight
    }
    document
      .querySelector('.operationMenu')
      .setAttribute('style', `top:${posY}px;left:${posX}px;z-index:99`)
    // document
    //   .querySelector('.operationMenu')
    //   .setAttribute('style', `top:${posY - 20}px;left:${posX - 30}px;`)
  })
}
const handleReturnOperation = (item) => {
  let status = item.note_place_status
  let obj = moreFilledbuttons.find((x) => x.id === '9')
  if (enumNoteSpace.unpubblish !== status && enumNoteSpace.fail !== status) {
    obj.label = '取消发布'
  } else {
    obj.label = '发布到笔记空间'
  }
  if (item.icon == 'Document') {
    return moreFilledbuttons
  } else {
    return moreFilledbuttons.filter((x) => x.id !== '6')
  }
}
const editTitleVisible = ref(false)
const deleteFile = ref(false)
const selectSortItem = ref()
const handleJumpEditNote = (item) => {
  MapJump[item.icon](item.id)
}
const appendParentData = ref({}) // 右击选中的节点
const textToCopy = ref({}) // 复制的内容
const noteTypes = ['Document', 'Xmind', 'FlowChart']
const labelVisible = ref(false) //关联标签弹窗
const moveVisible = ref(false)
const MapNoteOperations = {
  1: (item) => {
    // 重命名
    editTitleVisible.value = true
    fileForm.name = item.title
  },
  2: () => {
    // 移动
    moveVisible.value = true
  },
  3: (item) => {
    // 复制
    copyToClipboard(item)
  },
  4: async () => {
    // 粘贴
    if (noteTypes.includes(textToCopy.value.icon)) {
      const res = await httpCreateNote({
        folder_id: textToCopy.value.parent_id,
        title: '',
        content: textToCopy.value.content,
        icon: textToCopy.value.icon,
        label_id_list: textToCopy.value.label || [],
      })
      if (res) {
        ElMessage.success('粘贴成功')
        // TODO: 刷新快捷方式和文件夹列表
        noteState.getList()
        noteState.getFolderListData()
        noteState.getShortCutList()
      } else {
        ElMessage.error('粘贴失败')
      }
    }
  },
  5: () => {
    // 删除
    deleteFile.value = true
  },
  6: async (item) => {
    // 导出word
    const data = await asBlob(item.content, {
      orientation: 'landscape',
      margins: { top: 100 },
    })
    if (item.icon == 'Document') {
      downloadFile(data, item.title)
    }
  },
  7: (item) => {
    // 新窗口打开
    let href
    if (item.icon == 'Document') {
      href = router.resolve({
        path: `/file/doc/${item.id}`,
      }).href
    } else if (item.icon == 'Xmind') {
      href = router.resolve({
        path: `/file/mindmap/${item.id}`,
      }).href
    } else {
      href = router.resolve({
        path: `/file/drawio/${item.id}`,
      }).href
    }
    window.open(href, '_blank')
  },
  8: () => {
    // 关联标签
    labelVisible.value = true
  },
  9: (item) => {
    let status = item.note_place_status
    if (enumNoteSpace.unpubblish === status || enumNoteSpace.fail === status) {
      ElMessageBox.confirm('发布的笔记将公开', '确认发布到笔记空间吗?', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          const res = await httpPubblishNoteToNoteSpace({
            note_id: item.id,
          })
          if (res) {
            noteState.getList()
            ElMessage.success('发布成功')
          } else {
            ElMessage.error('发布失败')
          }
        })
        .catch(() => {})
    } else {
      ElMessageBox.confirm('取消发布笔记', '确认取消发布到笔记空间吗?', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          const res = await httpUnpublishFromNoteSpace({
            note_id: item.id,
          })
          if (res) {
            noteState.getList()
            ElMessage.success('取消成功')
          } else {
            ElMessage.error('取消失败')
          }
        })
        .catch(() => {})
    }
  },
}
const sortList = ref([
  {
    id: 1,
    label: '创建时间',
  },
  {
    id: 2,
    label: '更新时间',
  },
  {
    id: 3,
    label: '笔记名称',
  },
])
const mapSortFn = {
  1: () => {
    queryNote.value.sort_order = down.value ? 1 : 3
  },
  2: () => {
    queryNote.value.sort_order = down.value ? 1 : 4
  },
  3: () => {
    queryNote.value.sort_order = down.value ? 2 : 5
  },
}

const toggleSort = (item) => {
  if (currentId.value === item.id) {
    down.value = !down.value
  } else {
    currentId.value = item.id
    down.value = true
  }
  mapSortFn[item.id]()
  noteState.getList()
  selectSortItem.value = item
}
const handleOpenNote = async (btn, item) => {
  appendParentData.value = item
  MapNoteOperations[btn.id](item)
}
/**
 * 复制到粘贴板
 */
const copyToClipboard = async (content) => {
  try {
    textToCopy.value = content
    await navigator.clipboard.writeText(JSON.stringify(textToCopy.value))
    ElMessage.success('复制成功')
  } catch (err) {
    console.error('复制失败', err)
  }
}
/**
 * 粘贴
 * @param {*} event
 */
const paste = (event) => {
  if (event.ctrlKey && event.key === 'v') {
    // 读取粘贴板
    navigator.clipboard.readText().then(
      async (text) => {
        if (text) {
          try {
            let data = JSON.parse(text)
            if (noteTypes.includes(data.icon)) {
              const res = await httpCreateNote({
                folder_id: data.parent_id,
                title: '',
                content: data.content,
                icon: data.icon,
                label_id_list: data.label || [],
              })
              if (res) {
                ElMessage.success('粘贴成功')
                noteState.getList()
                noteState.getFolderListData()
                noteState.getShortCutList()
              } else {
                ElMessage.error('粘贴失败')
              }
            }
          } catch (error) {
            console.error('粘贴板内容不是json格式', error)
          }
        }
      },
      (err) => {
        console.error('无法读取粘贴板内容：', err)
      },
    )
  }
}
onMounted(async () => {
  // if (!route.params.id) {
  noteState.getList()
  // }
  document.addEventListener('keydown', paste)
})
onUnmounted(() => {
  document.removeEventListener('keydown', paste)
})

const handleSearch = debounce(() => {
  queryNote.value.page = 1
  noteState.getList()
}, 800)
watch(
  () => [selectedFolder.value, selectedTag.value],
  () => {
    if (selectedFolder.value || selectedTag.value) {
      // queryNoteLabel.page = 1
      queryNote.value.page = 1
      noteState.getList()
    }
  },
)
const submitForm = async (formEl) => {
  if (!formEl) return
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      if (appendParentData.value.title == fileForm.name) {
        editTitleVisible.value = false
        return
      }
      const res = await httpUpdatefolder({
        folder_id: appendParentData.value.id,
        name: fileForm.name,
      })
      if (res) {
        editTitleVisible.value = false
        queryNote.value.page = 1
        noteState.getList()
        noteState.getFolderListData()
        noteState.getShortCutList()
      }
    } else {
    }
  })
}
const resetForm = (formEl) => {
  if (!formEl) return
  editTitleVisible.value = false
  formEl.resetFields()
  fileForm.name = ''
}

const deleteNoteConfirm = async () => {
  let res = await httpDeleteNoteBook({
    detail_id: appendParentData.value.id,
  })
  if (res) {
    ElMessage.success('删除成功')
    queryNote.value.page = 1
    noteState.getList()
    noteState.getFolderListData()
    noteState.getShortCutList()
  } else {
    ElMessage.error('删除失败')
  }
  deleteFile.value = false
}
</script>
<style scoped lang="scss">
.search-header {
  width: 100%;
  display: flex;
  padding: 0 10px;
  .my-note {
    flex: 1;
    display: flex;
    flex-direction: column;
    & :nth-child(1) {
      font-size: 18px;
      font-weight: 500;
    }
    & :last-child {
      font-weight: 600;
    }
  }
  .search {
    flex: 1;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    flex-direction: column;
    gap: 4px;
    .sort-icons {
      display: flex;
      gap: 4px;
      cursor: pointer;
    }
  }
}
.note-box {
  height: calc(100vh - 100px);
  overflow: auto;
  background-color: #f8f9fa;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  .item-box {
    padding-left: 10px;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    :deep(.el-card__header) {
      padding: 0px 10px 0 !important;
      border: none !important;
    }
    :deep(.el-card__body) {
      padding: 0 10px !important;
      border: none !important;
    }
    :deep(.el-card__footer) {
      padding: 0 10px !important;
      border: none !important;
      text-align: end;
    }
  }
}
/* 滚动条样式 */
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
/* 滑块样式 */
::-webkit-scrollbar-thumb {
  background-color: #9f9f9f;
  border-radius: 10px;
}
/* 滚动条轨道样式 */
::-webkit-scrollbar-track {
  background-color: #fcfcfc;
  border-radius: 10px;
}

.list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  cursor: pointer;
}

.card-item {
  --el-card-border-color: var(--el-border-color-light);
  --el-card-border-radius: 4px;
  --el-card-padding: 20px;
  --el-card-bg-color: var(--el-fill-color-blank);
  background-color: var(--el-card-bg-color);
  border: 1px solid var(--el-card-border-color);
  border-radius: var(--el-card-border-radius);
  color: var(--el-text-color-primary);
  // overflow: hidden;
  transition: var(--el-transition-duration);
  padding: 10px;
  display: flex;
  align-items: center;
  &:hover {
    box-shadow: var(--el-box-shadow-light);
  }
}

.operationMenu {
  font-size: 14px;
  position: fixed;
  z-index: 9;
  // top: 50%;
  // left: 50%;
  background-color: #fff;
  border-radius: 5px;
  // background-color: #f2f3f5;
  display: flex;
  padding: 10px;
  flex-direction: column;
  box-shadow: var(--el-box-shadow-light);
}
</style>
